<?php
// Copyright 2008 Datapolis Solutions OY
// 
// This file is part of a program, that is distributed
// under the terms of the GNU General Public License,
// see license.txt for details.


require_once('DPFormBlock.php');
require_once('DPEventScheduleStore.php');

class DPEventSchedule extends DPFormBlock {
	
	const VIEW_MAP    = 0;
	const VIEW_TIME   = 1;
	const VIEW_PLACE  = 2;
	const TYPE_DAY    = 0;
	const TYPE_PERIOD = 1;
	
	private $esstore = null;
	
	public function __construct ( $opts )
	{
		parent::__construct($opts);
		
		// TODO to support multiple schedules DPEventScheduleStore->load doesn't work
		//      we should have an array of DPEventScheduleStore objects
		$this->esstore = new DPEventScheduleStore($this->db, $this->options['dpjoomla_id'], $this->options);
	}
	
	/**
	* Gets an instance of this singleton. If no instance exists, a new instance is created and returned.
	* If one does exist, then the existing instance is returned.
	*/
	public static function getInstance ( $opts ) 
	{
		static $instance;
		if ($instance === null) {
			$instance = new DPEventSchedule($opts);
		}
		return $instance;
	}
	
	/**
	* Get headers for html head.
	* 
	* @return string.
	*/
	public function getHeaders (  )
	{
		return ''
			// CSS
			.'<link href="'.$this->getCSSFileUrl('reset.css').'" rel="stylesheet" type="text/css" />'
			
			// Javascript
			.'<script src="'.$this->getJSFileUrl('jq.js').'" language="JavaScript" type="text/javascript"></script>'
			.($this->options['map'] === DPFormBlock::MAP_GOOGLE ?
				'<script src="http://maps.google.com/maps?file=api&amp;v=2&amp;key='.$this->options['google_map_key'].'" type="text/javascript"></script>'
					: ''
			)
			.'<script src="'.$this->getJSFileUrl('OpenLayers.js').'" language="JavaScript" type="text/javascript"></script>'
			.'<script src="'.$this->getJSFileUrl('OpenLayers.Click.js').'" language="JavaScript" type="text/javascript"></script>'
			.'<script src="'.$this->getJSFileUrl('OLDPPositionStyle.js').'" language="JavaScript" type="text/javascript"></script>'
			.'<script src="'.$this->getJSFileUrl('OLDPPositionMap.js').'" language="JavaScript" type="text/javascript"></script>'
			.($this->options['map'] === DPFormBlock::MAP_GOOGLE ?
				'<script src="'.$this->getJSFileUrl('OLDPPositionMap.Google.js').'" language="JavaScript" type="text/javascript"></script>'
					: ''
			)
			.($this->options['map'] === DPFormBlock::MAP_HEL ?
				'<script src="'.$this->getJSFileUrl('OLDPPositionMap.HEL.js').'" language="JavaScript" type="text/javascript"></script>'
					: ''
			)
		;
	}
	
	/**
	* Get editor (HTML, CSS, Javascript) for the form block.
	* Return value
	*   array(
	*     'html'       => '<div></div>',
	*     'css'        => '<style></style>',
	*     'javascript' => '<script></script>',
	*   )
	* 
	* @param  string  $formID  ID attribute of the form.
	* @param  int     $id      Null or an id of the stored item.
	* @return mixed            Array or false on failure.
	*/
	public function getEditor ( $formID, $id=null )
	{
		$id = ($id !== null) ? intval($id) : 0;
		if( $this->selfCheck() !== true ){
			return false;
		}
		
		// load data for edited from database
		if( $this->hasError() !== true && $id > 0 ){
			if( $this->esstore->load($id) !== true ){
				$this->appendErrors($this->esstore->getErrors());
				return false;
			}
		}
		
		// <<<EOT EOT;
		$js = 'jQuery(function (){
			var p = new OLDPPositionsEvent({
				formID:     "'.$formID.'",
				divID:      "dppositions",
				iconUrl:    "'.$this->options['iconUrl'].'",
				iconWidth:  '.$this->options['iconWidth'].',
				iconHeight: '.$this->options['iconHeight'].',
				eventID:    '.$id.',
				type:       '.$this->esstore->type.',
				dfltStatus: '.$this->options['default_status'].',
				dfltLon:    '.$this->options['default_map_lon'].',
				dfltLat:    '.$this->options['default_map_lat'].',
				dfltZoom:   '.$this->options['default_map_zoom'].',
				dfltPID:    '.$this->options['default_list_id'].'
			});'."\n";

		// show errors which are set in loadFormData()
		if( $this->hasError() ){
			$js .= 'p.showErrors([';
			foreach( $this->errorMsgs as $e ){
				$js .= '{msg: '.$this->jsQuote($e[2]).'},';
			}
			$js = substr($js, 0, -1).']);'."\n";
		}
		
		// show schedule edit form
		// 05.03.2009 - We're only interested in the time record here now - leif@sitelogic.fi
//		if( $this->esstore->position !== null ){
		if( $this->esstore->time !== null){
			// add positions
/*			05.03.2009 - Don't add the position information to the object - leif@sitelogic.fi
			$js .= 'p.addPosition({
					id:        '.$this->esstore->position->getId().',
					lon:       '.$this->esstore->position->getLon().',
					lat:       '.$this->esstore->position->getLat().',
					zoom:      '.$this->esstore->position->getZoom().',
					name:      '.$this->jsQuote($this->esstore->position->getName()).',
					details:   '.$this->jsQuote($this->esstore->position->getDetails()).',
					street:    '.$this->jsQuote($this->esstore->position->getStreet()).',
					status:    '.$this->esstore->position->getStatus().",\n";
*/
			$js .= 'p.addPosition({';
			if( $this->esstore->type === DPEventSchedule::TYPE_DAY ){
				$js .= '
					type:      '.DPEventSchedule::TYPE_DAY.',
					day_from:  '.$this->jsQuote($this->esstore->day_from->getDate(DPEventScheduleDate::FORMAT_FI)).',
					time_from: '.$this->jsQuote($this->esstore->time->getStarttime()).',
					time_to:   '.$this->jsQuote($this->esstore->time->getEndtime())."\n";
			}else if( $this->esstore->type === DPEventSchedule::TYPE_PERIOD ){
				$js .= '
					type:      '.DPEventSchedule::TYPE_PERIOD.',
					day_from:  '.$this->jsQuote($this->esstore->day_from->getDate(DPEventScheduleDate::FORMAT_FI)).',
					day_to:    '.$this->jsQuote($this->esstore->day_to->getDate(DPEventScheduleDate::FORMAT_FI))."\n";
			}else{
				$this->addError(__FILE__, __LINE__, "Unknown schedule TYPE");
				return false;
			}
			
			// end parameters array
			$js .= '});';
		}else{
			$js .= 'p.addDefaultPosition();';
		}
		
		// end jQuery function
		$js .= '});';
		
		return array(
			'html'       => '<div id="dppositions"></div>',
			'css'        => '<link href="'.$this->getCSSFileUrl('overlay.css').'" rel="stylesheet" type="text/css" />'
			                .'<link href="'.$this->getCSSFileUrl('form.event.css').'" rel="stylesheet" type="text/css" />',
			'javascript' => 
				'<script src="'.$this->getJSFileUrl('DPOverlay.js').'" language="JavaScript" type="text/javascript"></script>'
				.'<script src="'.$this->getJSFileUrl('OLDPPositions.js').'" language="JavaScript" type="text/javascript"></script>'
				.'<script src="'.$this->getJSFileUrl('OLDPPositionsEvent.js').'" language="JavaScript" type="text/javascript"></script>'
				.'<script src="'.$this->getJSFileUrl('OLDPPosition.js').'" language="JavaScript" type="text/javascript"></script>'
				.'<script src="'.$this->getJSFileUrl('OLDPPositionEvent.js').'" language="JavaScript" type="text/javascript"></script>'
				.'<script src="'.$this->getJSFileUrl('OLDPPredefined.js').'" language="JavaScript" type="text/javascript"></script>'
				.'<script type="text/javascript">'.trim($js).'</script>',
		);
	}
	
	/**
	* Gets values from sent form and validates the received values.
	* If this fails call getEditor() and show the form again.
	* 
	* @param  int  $id  Null or an id of the stored item.
	* @return boolean
	*/
	public function loadFormData (  )
	{
		// load form data
		if( $this->esstore->loadFormData(0) === true ){
			return true;
		}
		
		// store error messages
		$this->appendErrors($this->esstore->getErrors());
		return false;
	}
	
	/**
	* Store data which was loaded from the sent form.
	* 
	* @param  int  $id  An id of the stored item.
	* @return boolean
	*/
	public function storeFormData  ( $id )
	{
		// check that data loading is done
		if( $this->esstore->hasError() ){
			$this->addError(__FILE__, __LINE__, "DPEventScheduleStore::hasError() returned true");
			return false;
		}
		
		// remove all old schedules for this event id
		$sql = "DELETE FROM `#__dpcal_schedule` WHERE `id_e` = ".$id;
		$this->db->setQuery( $sql );
		if( $this->db->query() !== true ){
			$this->addError(__FILE__, __LINE__, $this->db->getErrorMsg());
			return false;
		}
		
		// store data
		if( $this->esstore->store($id) ){
			return true;
		}
		$this->appendErrors($this->esstore->getErrors());
		return false;
	}
	
	/**
	* Get view (HTML, CSS, Javascript) for the saved data.
	* Return value
	*   array(
	*     'html'       => '<div></div>',
	*     'css'        => '<style></style>',
	*     'javascript' => '<script></script>',
	*   )
	* 
	* @param  int  $id  An id of the stored item.
	* @return mixed     Array or false on failure.
	*/
	public function getView ( $id, $type=DPEventSchedule::VIEW_MAP )
	{
		global $_DPCAL_DAYS;
		
		$id = intval($id);
		if( $this->selfCheck() !== true ){
			return false;
		}
		
		// load position data from database
		if( $this->esstore->id_e !== $id ){
			if( $this->esstore->load($id) !== true ){
				$this->appendErrors($this->esstore->getErrors());
				return false;
			}
		}
		
		if( $type == DPEventSchedule::VIEW_TIME ){
			$html = '';
			if( $this->esstore->type === DPEventSchedule::TYPE_DAY ){
				$html = '<div class="event_time">
					<span class="event_startday">'.(isset($_DPCAL_DAYS) ? $_DPCAL_DAYS[date('l', $this->esstore->day_from->getTimestamp())] : '').'</span>
					<span class="event_startdate">'.$this->esstore->day_from->getDate(DPEventScheduleDate::FORMAT_FI).'</span>
					<span class="event_starttime">kello&nbsp;'.$this->esstore->time->getStarttime().'</span>'.($this->esstore->time->getEndtime() == '' ? '' : '&nbsp;&ndash;&nbsp;<span class="event_stoptime">'.$this->esstore->time->getEndtime().'</span>').'
				</div>';
			}else if( $this->esstore->type === DPEventSchedule::TYPE_PERIOD ){
				$html = '<div class="event_time">
					<span class="event_startdate">'.$this->esstore->day_from->getDate(DPEventScheduleDate::FORMAT_FI).'</span>
					<span class="event_enddate">'.$this->esstore->day_to->getDate(DPEventScheduleDate::FORMAT_FI).'</span>
				</div>';
			}
			return array(
				'html'       => $html,
				'css'        => '',
				'javascript' => '',
			);
		}else if( $type == DPEventSchedule::VIEW_PLACE ){
/* 05.03.2009 - Don't generate the html - leif@sitelogic.fi
		  // Helkamod 2008-11-20 / IK
		  $html = '<tr><th>Paikka</th><td>'.$this->esstore->position->getName().'</td></tr>';
		  if ($this->esstore->position->getStreet()) {
		    $html .= '<tr><td></td><td>'.$this->esstore->position->getStreet().'</td></tr>';
		  }
		  // end Helkamod
*/
		  $html = '';
		  return array(
			       'html'       => $html,
			       'css'        => '',
			       'javascript' => '',
			       );
		}else{
		  //05.03.2009 - Return empty result instead - leif@sitelogic.fi
		  return array(
			       'html'       => '',
			       'css'        => '',
			       'javascript' => '',
			       );
			// get positions from database
			$mapId = "dpposition_".md5(uniqid(rand(), true));
			$js = 'jQuery(function (){
				var m = new OLDPPositionMap({
					divID:      "'.$mapId.'",
					iconUrl:    "'.$this->options['iconUrl'].'",
					iconWidth:  '.$this->options['iconWidth'].',
					iconHeight: '.$this->options['iconHeight'].'
				});
				m.addPosition('.$this->esstore->position->getLon().','.$this->esstore->position->getLat().','.$this->esstore->position->getZoom().');
				m.centerMap();
			});';
			
			return array(
				'html'       => '<div class="event_place">
						<div class="name">'.$this->esstore->position->getName().'</div>
						<div class="address">'.(strlen($this->esstore->position->getStreet()) > 0 ? $this->esstore->position->getStreet() : '&nbsp;').'</div>
						<div id="'.$mapId.'" class="event_map_image"></div>
					</div>',
				'css'        => '',
				'javascript' => '<script type="text/javascript">'.$js.'</script>',
			);
		}
	}
	
	/**
	* Remove all data related to the passed id.
	* 
	* @param  int  $id  An id of the stored item.
	* @return boolean
	*/
	public function remove ( $id )
	{
		// get dpposition_ids from dpcal_schedule (GROUP BY dpposition_id)
		$sql = "SELECT `dpposition_id` 
			FROM `#__dpcal_schedule` 
			WHERE `id_e` = ".$id." 
			GROUP BY `dpposition_id`";
		$this->db->setQuery( $sql );
		//echo $this->db->_sql;
		$dpposition_ids = $this->db->loadAssocList();
		if( is_array($dpposition_ids) !== true ){
			$this->addError(__FILE__, __LINE__, $this->db->getErrorMsg());
			return false;
		}
		
		// remove schedule rows
		$sql = "DELETE FROM `#__dpcal_schedule` WHERE `id_e` = ".$id;
		$this->db->setQuery( $sql );
		if( $this->db->query() !== true ){
			$this->addError(__FILE__, __LINE__, $this->db->getErrorMsg());
			return false;
		}
		
		// remove obsolate dppositions
		//   not used (no rows in dpcal_schedule) and have status STATUS_USER
		foreach($dpposition_ids as $dpposition_id){
			$sql = "DELETE a, b, c
				FROM 
					`#__dpposition` AS a 
					LEFT JOIN `#__dpposition_has_alias` AS b ON (
						b.`dpposition_id` = a.`dpposition_id`
					)
					LEFT JOIN `#__dpposition_has_tag` AS c ON (
						c.`dpposition_id` = a.`dpposition_id`
					)
				WHERE 
					a.`dpposition_id` = {$dpposition_id['dpposition_id']} 
					AND a.`dpposition_id` NOT IN (
						SELECT d.`dpposition_id` FROM `#__dpcal_schedule` AS d WHERE d.`dpposition_id` = {$dpposition_id['dpposition_id']} 
					)
					AND a.`dpposition_status` = ".$this->db->Quote(DPFormBlock::STATUS_USER);
			$this->db->setQuery( $sql );
			//echo $this->db->_sql;
			if( $this->db->query() !== true ){
				$this->addError(__FILE__, __LINE__, $this->db->getErrorMsg());
				return false;
			}
		}
		return true;
	}
}

?>